# odump.S

#include <mips/regdef.h>
#include <sys/syscall.h>

#define ERROR_CARACTER_INVALIDO 1
#define ERROR_LECTURA_ESCRITURA_ARCHIVO 2
#define ERROR_DELIM_INVALIDO 3

//BYTES_COUNT: tercer argumento de SYS_READ (cuantos bytes lee)
#define BYTES_COUNT	1
#define BYTES_COUNT_PRINT	4


#definicion del vector de mensajes
.rdata		//Para que sea constante durante la ejecucion
.align 2

//A continuacion los mensajes de error a los que apuntara el vector
msg1:
	.asciiz "El caracter es invalido\n"

msg2:
	.asciiz "Error al intentar leer/escribir un archivo\n"

msg3:
	.asciiz "El delimitador no es el correcto\n"

.globl odump_errmsg		//Declaro global al vector
odump_errmsg:			//Definicion del vector de mensajes de error
	.align 2
	.word msg1,msg2,msg3

caracterSaltoDeLinea:
	.asciiz		"\n"

stringAImprimir:
	.asciiz		"%s"

.data
caracteresOctales:
	.asciiz		"%.*o"

intAImprimir:
	.asciiz		"%d\n"

charAImprimir:
	.asciiz		"%c\n"

buffer:
	.space	1

octBuffer:
	.space	4	//Espacio para caracteres que conforman el byte octal


.text
.align 2

/************************************************************************************************/

.ent caracteresNoIguales

caracteresNoIguales:
	//Stack Frame = gp, fp

	.frame		$fp,8,ra				//creo el stack frame
	.set		noreorder
	.cpload		t9
	.set		reorder
	subu		sp,sp,8					//Reservo 24 bytes para el stack frame
	.cprestore	0						//Guarda gp en sp
	sw			$fp,8(sp)				//Guarda fp

	sw			a0,8(sp)
	sw			a1,12(sp)
	lw			t0,8(sp)					//Muevo argumentos a registros
	lw			t1,12(sp)
	beq			t0,t1,salidaCaracteresIguales	//Comparo registros. Si son iguales, debe retornar 0
	li			t0,ERROR_DELIM_INVALIDO			//Debo manejar los codigos de error
	li			a3,1							//Seteo flag de error
	b			retornoCaracteresNoIguales

salidaCaracteresIguales:
	li			t0,0			//Guardo en t0 el valor que debe retornar

retornoCaracteresNoIguales:
	move		v0,t0			//Muevo a v0 el valor que debe retornar
	lw			gp,0(sp)		//comienzo a desarmar el stack frame
	lw			$fp,4(sp)
	addu		sp,sp,8
	j ra

.end caracteresNoIguales

/************************************************************************************************/

.ent isNotOctalDigit
.align 2

isNotOctalDigit:						//Compara codigo ASCII de caracteres

	//Stack Frame = gp, fp

	.frame		$fp,8,ra				//creo el stack frame
	.set		noreorder
	.cpload		t9
	.set		reorder
	subu		sp,sp,8					//Reservo 24 bytes para el stack frame
	.cprestore	0						//Guarda gp en sp+16
	sw			$fp,4(sp)				//Guarda fp

	sw			a0,8(sp)
	lw			t0,8(sp)				//Muevo argumento a t0
	li			t1,55					//Cargo 55 a t1 para comparar con t0
	bgt			t0,t1,salidaNoEsOctal	//Si t0 > 55 (7 en ASCII), no es octal
	li			t1,48					//Cargo 48 a t1 para comparar con t0
	blt			t0,t1,salidaNoEsOctal	//Si t0 < 48 (0 en ASCII), no es octal
	li			t0,0					//Cargo 0 en t0 para retornar
	b			retornoIsNotOctalDigit

salidaNoEsOctal:

	li			t0,ERROR_CARACTER_INVALIDO	//Cargo el error correspondiente
	li			a3,1						//Activo flag de error

retornoIsNotOctalDigit:

	move		v0,t0				//Cargo en el registro correspondiente

	lw			gp,0(sp)			//comienzo a desarmar el stack frame
	lw			$fp,4(sp)
	addu		sp,sp,8

	j			ra					//valor de retorno

.end isNotOctalDigit

/************************************************************************************************/

.ent isNotValidChar
.align 2

isNotValidChar:								//Verifica los ASCII para ver si es
											//caracter valido el pasado por a0
	//Stack Frame = gp, fp

	.frame		$fp,8,ra				//creo el stack frame
	.set		noreorder
	.cpload		t9
	.set		reorder
	subu		sp,sp,8					//Reservo 24 bytes para el stack frame
	.cprestore	0						//Guarda gp en sp+16
	sw			$fp,4(sp)				//Guarda fp

	sw			a0,8(sp)
	lw			t0,8(sp)
	li			t1,255							//Cargo maximo ASCII valido
	bgt			t0,t1,salidaNoEsCaracterValido	//Comparo si argumento es mayor
	li			t1,0							//Cargo minimo ASCII valido
	blt			t0,t1,salidaNoEsCaracterValido	//Comparo si argumento es menor
	li			t0,0							//Caracter valido, cargo 0 para retornar
	b			retornoIsNotValidChar

salidaNoEsCaracterValido:

	li			t0,ERROR_CARACTER_INVALIDO		//Cargo el error correspondiente
	li			a3,1							//Activo flag error

retornoIsNotValidChar:

	move	v0,t0							//Cargo valor de retorno

	lw			gp,0(sp)				//comienzo a desarmar el stack frame
	lw			$fp,4(sp)
	addu		sp,sp,8

	j		ra

.end isNotValidChar

/************************************************************************************************/

.ent potenciasDe8
.align 2

potenciasDe8:						//Realiza el calculo de las potencias de 8
	//Stack Frame = gp, fp

	.frame		$fp,8,ra			//creo el stack frame
	.set		noreorder
	.cpload		t9
	.set		reorder
	subu		sp,sp,8				//Reservo 24 bytes para el stack frame
	.cprestore	0					//Guarda gp en sp+16
	sw			$fp,4(sp)			//Guarda fp

	sw			a0,8(sp)
	lw			t0,8(sp)			//Muevo argumento (exponente) a t0
	beqz t0,salidaExpEs0			//Si el exponente es 0 retorno 1
	li t1,8							//Cargo 8 a t1 para tener la base
	li t2,8

loop:
	addi t0,-1						//Resto 1 al exponente, ya que se realizan exp-1 multiplicaciones
	beqz t0,retornopotenciasDe8
	mul t2, t2, t1					//t2 = t2 * t1, donde en t1 hay un 8
	b loop

salidaExpEs0:
	li t2,1							//Cargo un 1 en t2

retornopotenciasDe8:
	move	v0,t2					//Cargo en el registro correspondiente

	lw			gp,0(sp)				//comienzo a desarmar el stack frame
	lw			$fp,4(sp)
	addu		sp,sp,8

	j		ra						//valor de retorno

.end potenciasDe8

/************************************************************************************************/

.ent decAOctal
.align 2

decAOctal:
	//Stack Frame = gp, fp

	.frame		$fp,8,ra				//creo el stack frame
	.set		noreorder
	.cpload		t9
	.set		reorder
	subu		sp,sp,8					//Reservo 24 bytes para el stack frame
	.cprestore	0						//Guarda gp en sp+16
	sw			$fp,4(sp)				//Guarda fp

	sw			a0,8(sp)
	lw			t0,8(sp)				//Muevo argumento a t0
	la			t1,octBuffer
	sb			zero,0(t1)
	sb			zero,1(t1)
	sb			zero,2(t1)
	sb			zero,3(t1)
	addi		t1,t1,2
	li			t3,3					//Counter = 3

loopDecAOctal:

	remu	t2,t0,8					//Divisiones sucesivas entre 8
	sb		t2,0(t1)				//Guardo el resto en el buffer
	addi	t1,t1,-1				//Resto posicion para puntero a buffer
	divu	t0,t0,8					//Divido por 8
	addi	t3,t3,-1				//counter -= 1
	bne		t3,zero,loopDecAOctal	//Si el counter es 0, salgo del loop

salidaDecAOctal:

	lw			gp,0(sp)				//comienzo a desarmar el stack frame
	lw			$fp,4(sp)
	addu		sp,sp,8

	j		ra

.end decAOctal

/************************************************************************************************/

.ent	string_len
.align	2

string_len:		//Cuenta longitud de char*. a0 = char* (terminado con '\0')
	//Stack Frame = gp, fp

	.frame		$fp,8,ra				//creo el stack frame
	.set		noreorder
	.cpload		t9
	.set		reorder
	subu		sp,sp,8					//Reservo 24 bytes para el stack frame
	.cprestore	0						//Guarda gp en sp+16
	sw			$fp,4(sp)				//Guarda fp

	sw			a0,8(sp)
	lw			t0,8(sp)				//muevo argumento a t0
	move		t1,zero					//inicializo contador

loopStringLen:

	lb		t2,0(t0)					//cargo el primer caracter del string
	beq		t2,zero,finStringLen
	addi	t0,1						//muevo un byte hacia adelante
	addi	t1,1						//sumo el counter
	b		loopStringLen				//vuelvo al loop

finStringLen:

	move	v0,t1						//Devuelvo el counter (cant caracteres)

	lw			gp,0(sp)				//comienzo a desarmar el stack frame
	lw			$fp,4(sp)
	addu		sp,sp,8

	j		ra

.end	string_len

/************************************************************************************************/

.globl odump_encode
.ent odump_encode
.align 2

odump_encode:	//funcion codificar

	.frame		$fp,40,ra				//creo el stack frame
	.set		noreorder
	.cpload		t9
	.set		reorder
	subu		sp,sp,40				//Reservo 40 bytes para el stack frame
	.cprestore	28						//Guarda gp en sp+28
	sw			$fp,32(sp)				//Guarda fp
	sw			ra,36(sp)				//Guarda ra
	sw			a0,40(sp)				//Guardo argumentos en stack frame de
	sw			a1,44(sp)				//funcion que llamo a odump_encode
	sw			a2,48(sp)
	lw			s0,40(sp)
	lw			s1,44(sp)
	lw			s3,48(sp)
	lw			s2,0(s3)				//cargo length en s2
	lw			s3,4(s3)				//cargo el delimitador en s3
	move		$fp,sp
	move		s4,zero					//variable local, counter = 0
	li			s5,3					//variable local, cant_bytes = 3
	li			v0,SYS_read				//Cargo la syscall para leer
	move		a0,s0
	la			a1,buffer				//cargo buffer como argumento para read
	li			a2,BYTES_COUNT			//Cargo los bytes que debe leer
	syscall								//c = fgetc();

	beq			a3,1,salidaErrorArchivo	//Veo si syscall devuelve error
	beq			v0,zero,salidaEOF
	bne			v0,BYTES_COUNT,salidaErrorArchivo	//Veo si syscall devuelve cant bytes correspondientes


loopWhileNotEofEncoding:

	beq			s2,zero,counterHandler
	beq			s2,s4,lengthIgualCounter

counterHandler:
	bne			s4,zero,counterNotZero	//counter != 0
	b			endLoopWhileNotEofEncoding

counterNotZero:

	move		a0,s3					//cargo delimitador
	la			t9,string_len
	jal			t9						//cuento cantidad de caracteres
	sw			v0,16(sp)				//guardo cantidad de caracteres
	lw			t1,16(sp)				//cargo cantidad de caracteres
	beq			t1,zero,endLoopWhileNotEofEncoding	//Si strlen(delim) = 0, vuelve
	li			v0,SYS_write
	move		a0,s1					//Cargo output file descriptor
	move		a1,s3					//Cargo delimitador
	move		a2,t1					//Cargo los bytes que debe imprimir
	syscall
	li			t0,1
	beq			a3,t0,salidaErrorArchivo	//Compruebo flag de error
	beq			v0,zero,salidaErrorArchivo	//Comprueba EOF
	lw			t0,16(sp)
	bne			v0,t0,salidaErrorArchivo	//Comprueba que escribio cantidad correcta

	b			endLoopWhileNotEofEncoding

lengthIgualCounter:

	li			v0,SYS_write			//Cargo la syscall para escribir
	move		a0,s1					//Cargo output como argumento
	la			a1,caracterSaltoDeLinea	//Cargo lo que va a imprimir
	li			a2,BYTES_COUNT			//Cargo los bytes que debe imprimir
	syscall
	li			t0,1					//Compruebo errores archivo
	beq			a3,t0,salidaErrorArchivo	//Si devuelve error
	beq			v0,zero,salidaErrorArchivo	//Si devuelve EOF
	bne			v0,BYTES_COUNT,salidaErrorArchivo	//Si no escribio lo esperado

	move		s4,zero					//Reseteo el counter

endLoopWhileNotEofEncoding:
	//Instrucciones comunes a odump_encoder al finalizar el loop del while

	lbu			a0,buffer				//Cargo argumento de decAOctal
	jal			decAOctal

	la			s6,octBuffer
	li			s7,3

loopOctWriting:
	move		a0,s1					//Cargo output file descriptor
	lbu			t0,0(s6)
	addiu		t0,t0,48				//Sumo ASCII '0'
	sb			t0,buffer
	la			a1,buffer
	li			a2,BYTES_COUNT
	li			v0,SYS_write
	syscall

	beq			a3,1,salidaErrorArchivo			//Error al escribir
	beq			v0,zero,salidaErrorArchivo			//EOF de archivo a escribir
	bne			v0,BYTES_COUNT,salidaErrorArchivo	//Compruebo escribio cantidad de bytes correctos
	addi		s6,s6,1
	addi		s7,s7,-1
	bne			s7,zero,loopOctWriting

	addi		s4,s4,1					// counter = counter + 1
	li			v0,SYS_read
	move		a0,s0					// muevo input file descriptor
	la			a1,buffer				//Cargo el buffer
	li			a2,BYTES_COUNT			//Cargo los bytes que debe leer
	syscall
	beq			a3,1,salidaErrorArchivo	//Compruebo flag de error
	bne			v0,zero,loopWhileNotEofEncoding		//Si no es EOF, vuelve al while


salidaEOF:
	move		t0,zero					//si EOF, termina funcion, retorna 0
	b			retornoOdump_Encoding

salidaErrorArchivo:
	li			t0,ERROR_LECTURA_ESCRITURA_ARCHIVO	//Carga valor retorno

retornoOdump_Encoding:
	move		v0,t0					//muevo a v0 lo que devuelve la funcion
	lw			gp,28(sp)				//comienzo a desarmar el stack frame
	lw			$fp,32(sp)
	lw			ra,36(sp)
	addu		sp,sp,40
	j			ra

.end odump_encode

/************************************************************************************************/

.ent octalADecimal
.align 2

octalADecimal:						//Realiza la conversion de un numero octal a decimal

	.frame 	$fp,40,ra				//Creo el Stack Frame
	.set 	noreorder
	.cpload t9
	.set 	reorder
	subu 	sp,sp,40
	.cprestore 28					//Guardo el global pointer en el SF
	sw 		$fp,32(sp)				//Guardo el frame pointer en el SF
	sw 		ra,36(sp)				//Guardo el return address en el SF
	move 	$fp,sp
	sw 		a0,40($fp)
	sw 		zero,16($fp)			//16(fp) -> valor
	sw 		zero,20($fp)			//20(fp) -> decimal

	move 	t0,a0					//Muevo argumento (octal) a t0
	bgtz 	t0,loopOctDec					//Mientras octal sea mayor que 0 entro al loop
	b 		retornooctalADecimal	//Si no entra al loop, devuelvo el cero cargado en t2

loopOctDec:

	remu	t1,t0,10				//digito = octal%10
	sw		t1,24($fp)				//24(fp) -> digito
	lw		t0,40($fp)				//Cargo en t0 el valor de a0 guardado en el Stack Frame
	div		t1,t0,10				//octal /= 10
	sw		t1,40($fp)				//Guardo el resultado en el Stack Frame
	lw		a0,16($fp)				//Cargo en a0 valor, para el llamado a potenciasDe8
	la		t9,potenciasDe8			//Cargo la direccion de potenciasDe8
	jal 	t9						//Efectuo el llamado. El resultado esta en v0
	lw		t1,24($fp)				//Cargo en t1 el valor de digito
	mul		t1,t1,v0				//Guardo en t1 el resultado del producto entre digito y la potencia de 8
	lw		t2,20($fp)				//Cargo valor de decimal en t2
	addu	t1,t1,t2				//decimal = t1 = decimal + digito*potenciasDe8(valor)
	sw		t1,20($fp)				//decimal = t1
	lw		t0,16($fp)				//Bajo a t0 valor
	addi	t0,1					//Le sumo 1 a valor
	sw		t0,16($fp)				//Guardo valor en el Stack Frame
	lw		t0,40($fp)				//Bajo a t0 el valor de octal
	bgtz 	t0,loopOctDec			//Mientras octal sea mayor que 0 entro al loop


retornooctalADecimal:
	lw 		v0,20($fp)				//Cargo en el registro correspondiente el valor de retorno
	lw 		gp,28(sp)				//Destruyo el stack frame y recupero los datos necesarios
	lw 		$fp,32(sp)
	lw 		ra,36(sp)
	addu 	sp,sp,40
	j		ra

.end octalADecimal

/************************************************************************************************/

.ent	arrToInteger
.align 	2

arrToInteger:	//Convierte un arreglo de int en su equivalente integer
				//a0 = char*
	//Stack Frame = gp, fp

	.frame		$fp,8,ra				//creo el stack frame
	.set		noreorder
	.cpload		t9
	.set		reorder
	subu		sp,sp,8					//Reservo 8 bytes para el stack frame
	.cprestore	0						//Guarda gp en sp
	sw			$fp,4(sp)				//Guarda fp

	sw			a0,8(sp)
	lw			t0,8(sp)	//Muevo argumento a t0
	li 			t2,0	//Inicializo el contador

loopArrToInteger:
	lb 			t1,0(t0) 							//Carga el primer char
	addu 		t0,t0,1							//Incrementa la direccion de char*
	beq			t1,zero,finArrToInteger
	mul			t2,t2,10						//Mutiplico por 10 t2 para simular los cambios de unidad
	subu		t1,t1,48						//Le resto el '0' (48)
	add			t2,t2,t1						//Le sumo t1 al contador
	b			loopArrToInteger

finArrToInteger:
	move	v0,t2							//Devuelvo t2

	lw			gp,0(sp)				//comienzo a desarmar el stack frame
	lw			$fp,4(sp)
	addu		sp,sp,8

	j		ra

.end	arrToInteger

/************************************************************************************************/

.globl odump_decode
.ent odump_decode
.align 2

odump_decode:						//Funcion decodificar
	.frame 	$fp,48,ra				//Creo el Stack Frame
	.set 	noreorder
	.cpload t9
	.set 	reorder
	subu 	sp,sp,48
	.cprestore 36					//Guardo el global pointer en el SF
	sw 		$fp,40(sp)				//Guardo el frame pointer en el SF
	sw 		ra,44(sp)				//Guardo el return address en el SF
	move 	$fp,sp
	sw		a0,48($fp)				//Guardo argumentos en ABA del caller
	sw		a1,52($fp)
	sw		a2,56($fp)
	lw		s0,48($fp)				//Guardo los argumentos en los registros s0 a s3
	lw		s1,52($fp)				//s0 = infd ; s1 = outfd
	lw		s3,56($fp)
	lw		s2,0(s3)				//Cargo length en s2
	lw		s3,4(s3)				//Cargo el delimitador en s3

	sw 		zero,16($fp)			//16($fp) -> i
	li		t0,3					//Cargo un 3 en t0
	sw 		t0,20($fp)				//20($fp) -> limite

	/*		32($fp) -> Oct[0]
			33($fp) -> Oct[1]
			34($fp) -> Oct[2]
			35($fp) -> Oct[3]	*/
	sb		zero,35($fp)			//32($fp) -> oct	Inicializo en cero el byte nenos significativo de oct (Padding)


loopWhileNotEofDecoding:
	li		t8,0					//i = 0
	sw		t8,16($fp)				//Guardo el valor de i en el Stack Frame

cicloForDecoding:
	lw		t1,20($fp)				//Cargo en t1 el valor del limite
	lw		t8,16($fp)
	bge		t8,t1,comprobacionesLuegoFor	//Compruebo i < limite. Si no se cumple salto

	sb		zero,buffer				//Limpio el buffer

	move 	a0,s0					//Cargo en a0 el infd
	la		a1,buffer				//Cargo buffer como argumento para read
	li		a2,BYTES_COUNT			//Cargo los bytes que debe leer
	li		v0,SYS_read				//Cargo la syscall para leer
	syscall							//Realizo fgetc(), el resultado esta en v0

	lb		s4,buffer				//Cargo en s4 el valor de num devuelto por el read
	sw		s4,24($fp)				//Guardo num en el Stack Frame

	li		t0,1					//Realizo comprobarErrorArchivo
	beq		a3,t0,salidaErrorArchDecode		//Veo si syscall devuelve error
	li		t1,10							//Cargo en t1 el ASCII de '\n'
	beq		s4,t1,comprobacionesLuegoFor	//Si num = '\n' hago break
	li		t1,0							//Ahora cargo en t1 el ASCII de '\0'
	bne		v0,t1,finCicloForDecoding		//Si no es el fin de archivo, salto al fin del ciclo
	li		t3,0							//Si llego aca entonces debo retornar 0
	b		retornoOdump_Decoding


finCicloForDecoding:				//Lineas 239 y 240 de main.c más incremento de variable i y retorno
	sw		s4,24($fp)				//Guardo num en el Stack Frame
	move	a0,s4					//Cargo en a0 num, para el llamado a isNotOctalDigit
	la		t9,isNotOctalDigit		//Cargo la direccion de isNotOctalDigit
	jal 	t9						//Efectuo el llamado. El resultado esta en v0
	li		t0,1					//Cargo un 1 en t0, representando un error en isNotOctalDigit
	beq		v0,t0,salidaCaracterInvalidoDecode	//Si isNotOctalDigit devuelve 1, existio un error y salgo, sino sigo

	lw		s4,24($fp)				//Cargo en s4 el valor de num
	lw		t0,16($fp)				//Cargo en t0 el valor de i
	move	t1,$fp					//Cargo en t1 el inicio del Stack Frame
	add		t0,t0,t1				//Hago t0 = Inicio de Stack + i
	sb		s4,32(t0)				//Guardo en la posicion indicada el valor de num

	lw		t8,16($fp)				//Cargo en t8 el valor de i
	addi	t8,1					//i += 1
	sw		t8,16($fp)				//Guardo el valor de i en el Stack Frame
	b		cicloForDecoding		//Vuelvo a iterar en el ciclo for


comprobacionesLuegoFor:
	lw		s4,24($fp)				//Cargo en s4 el valor de num
	li		t1,10					//Cargo en t1 el ASCII de '\n'
	beq		s4,t1,loopWhileNotEofDecoding	//Si num = '\n' hago continue

	la		a0,32($fp)				//Cargo en a0 la direccion de oct para el llamado a atoi (arrToInteger)
	la		t9,arrToInteger			//Cargo la direccion de arrToInteger
	jal		t9						//Realizo arrToInteger, el resultado esta en v0
	move	s4,v0					//Cargo en s4 el resultado de arrToInteger
	sw		s4,24($fp)				//Guardo el valor de num en el Stack Frame

	move	a0,s4					//Cargo en a0 el valor de num para el llamado a octalADecimal
	la		t9,octalADecimal		//Cargo la direccion de octalADecimal
	jal		t9						//Realizo octalADecimal, el resultado esta en v0
	move	s5,v0					//Cargo en s5 el resultado de octalADecimal
	sw		s5,28($fp)				//Guardo el valor de dec en el Stack Frame

	move	a0,s5					//Cargo en a0 el valor de dec para el llamado a isNotValidChar
	la		t9,isNotValidChar		//Cargo la direccion de isNotValidChar
	jal		t9						//Realizo isNotValidChar, el resultado esta en v0
	li		t0,1					//Cargo un 1 en t0, representando un error en isNotValidChar
	beq		v0,t0,salidaCaracterInvalidoDecode	//Si isNotValidChar devuelve 1, existio un error y salgo, sino sigo

impresionEnOutputFile:
	li			t1,BYTES_COUNT			//Cargo un 1 en t1 por la cantidad de bytes de un int
	lw			a0,52($fp)				//Cargo output file descriptor
	la			a1,28($fp)				//Cargo el buffer con la direccion de dec
	move		a2,t1					//Cargo los bytes que debe imprimir
	li			v0,SYS_write
	syscall								//Realizo la syscall. El resultado es devuelto en v0
	li			t0,1					//Cargo -1 en t1 para comprobar un error en la escritura
	beq			a3,t0,salidaErrorArchDecode
	beq			v0,zero,salidaErrorArchDecode	//Compruebo EOF
	li			t0,BYTES_COUNT
	bne			v0,t0,salidaErrorArchDecode		//Compruebo haber escrito cantidad correcta

comprobacionesDelimitador:
	move	a0,s3					//Cargo en a0 a delim para el llamado a string_len
	la		t9,string_len			//Cargo la direccion de string_len en t9
	jal		t9						//Efectuo el llamado. El resultado esta en v0
	beqz	v0,loopWhileNotEofDecoding //Si el largo de delim es cero (es vacio), vuelvo a comenzar el ciclo

	move 	a0,s0					//Cargo en a0 el infd
	la		a1,buffer				//Cargo buffer como argumento para read
	li		a2,BYTES_COUNT			//Cargo los bytes que debe leer
	li		v0,SYS_read				//Cargo la syscall para leer
	syscall							//Realizo fgetc(), el resultado esta en v0

	lb		s4,buffer				//Guardo en s4 el valor de num devuelto por el read
	sw		s4,24($fp)				//Guardo num en el Stack Frame
	li		t0,1					//Realizo comprobarErrorArchivo
	beq		a3,t0,salidaErrorArchDecode		//Veo si syscall devuelve error

	li		t1,10							//Cargo en t1 el ASCII de '\n'
	beq		s4,t1,loopWhileNotEofDecoding	//Si num = '\n' vuelvo a empezar el ciclo, sino sigo
	li		t1,0							//Ahora cargo en t1 un 0 para comprobar EOF
	beq		v0,t1,loopWhileNotEofDecoding	//Si es el fin de archivo vuelvo a empezar el ciclo, sino sigo

	lw		a0,24($fp)				//Cargo num en a0 para el llamado a caracteresNoIguales
	lb		a1,0(s3)				//Cargo delim[0] en a1 para el llamado a caracteresNoIguales
	la 		t9,caracteresNoIguales	//Cargo la direccion de caracteresNoIguales en t9
	jal		t9						//Efectuo el llamado. El resultado esta en v0
	li		t0,1					//Cargo un 1 en t0 para comprobar el resultado de caracteresNoIguales
	beq		v0,t0,salidaDelimInvalidoDecode	//Si devolvio 1, retorno el error

	move	a0,s3					//Cargo en a0 a delim para el llamado a string_len
	la		t9,string_len			//Cargo la direccion de string_len en t9
	jal		t9						//Efectuo el llamado. El resultado esta en v0
	move	s7,v0					//Muevo el largo a t1
	li		s6,1					//Cargo en s6 el valor inicial de i = 1

forDeDelim:
	bge		s6,s7,loopWhileNotEofDecoding	//Compruebo i < strlen(delim). Si no se cumple empiezo de nuevo el while
	move 	a0,s0					//Cargo en a0 el infd
	la		a1,buffer				//Cargo buffer como argumento para read
	li		a2,BYTES_COUNT			//Cargo los bytes que debe leer
	li		v0,SYS_read				//Cargo la syscall para leer
	syscall							//Realizo fgetc(), el resultado esta en v0

	lb		s4,buffer				//Guardo en s4 el valor de num devuelto por el read
	li		t0,1					//Realizo comprobarErrorArchivo
	beq		a3,t0,salidaErrorArchDecode		//Veo si syscall devuelve error. En ese caso salgo con error

	la		t0,0(s3)				//Cargo la dirección de memoria de delim en t0 para acceder a delim[i]
	add		t0,t0,s6				//Le sumo a la direccion de memoria de delim el valor de i
	lb		a1,0(t0)				//Cargo en a1 el byte i de delim
	lw		a0,24($fp)				//Cargo num en a0 para el llamado a caracteresNoIguales
	la 		t9,caracteresNoIguales	//Cargo la direccion de caracteresNoIguales en t9
	jal		t9						//Efectuo el llamado. El resultado esta en v0
	li		t0,1					//Cargo un 1 en t0 para comprobar el resultado de caracteresNoIguales
	beq		v0,t0,salidaDelimInvalidoDecode	//Si devolvio 1, retorno el error

	addi	s6,1					//i += 1
	b		forDeDelim				//Vuelvo a iterar en el ciclo for


salidaCaracterInvalidoDecode:
	li 		t3,ERROR_CARACTER_INVALIDO
	b 		retornoOdump_Decoding

salidaDelimInvalidoDecode:
	li 		t3,ERROR_DELIM_INVALIDO
	b 		retornoOdump_Decoding

salidaErrorArchDecode:
	li 		t3,ERROR_LECTURA_ESCRITURA_ARCHIVO

retornoOdump_Decoding:
	move	v0,t3					//Cargo en v0 el valor de retorno, que se recibe en t3 por convencion
	lw 		gp,36(sp)				//Destruyo el stack frame y recupero los datos necesarios
	lw 		$fp,40(sp)
	lw 		ra,44(sp)
	addu 	sp,sp,48
	j		ra

.end odump_decode

